#pragma once
#include "Common.hpp"
#include "Session.hpp"
/*负责管理所有session
成员
        1.session_id计数器
        2.互斥锁
        3.分配器--session_id ->session_ptr
        4.WebServer指针,用于分配定时器对象
*/
using Session_ptr = std::shared_ptr<Session>;
#define SESSION_TIMEOUT 30000
#define SESSION_FOREVER -1
class SessionManager
{
private:
        LL _dispatch_session_id;
        std::mutex _mtx;
        std::unordered_map<LL, Session_ptr> _sessions;
        WebSocketServer *_server;

public:
        SessionManager(WebSocketServer *server)
            : _dispatch_session_id(1),
              _server(server)
        {
                LOG(DEBUG, "创建SessionManager done\n");
        }
        // 创建
        Session_ptr CreateSession(LL uid, SESSION_STATU statu)
        {
                std::unique_lock<std::mutex> lock(_mtx);
                Session_ptr session = std::make_shared<Session>(_dispatch_session_id);
                session->SetUid(uid);
                session->SetStatu(statu);
                _sessions.insert({_dispatch_session_id, session});
                ++_dispatch_session_id;
                return session;
        }
        // 获取
        Session_ptr SessionPtr(LL session_id)
        {
                std::unique_lock<std::mutex> lock(_mtx);
                auto iter = _sessions.find(session_id);
                if (iter == _sessions.end())
                {
                        return nullptr;
                }
                return iter->second;
        }
        void AppendSession(const Session_ptr &session)
        {
                std::unique_lock<std::mutex> lock(_mtx);
                _sessions.insert({session->SessionId(), session});
        }
        // 设置session过期时间
        void SetSessionExpireTime(LL session_id, int ms)
        {
                std::unique_lock<std::mutex> lock(_mtx);
                /*问题：
                        1.第一步应该做什么？先找到id对应的被管理的session_ptr！*/
                Session_ptr session = SessionPtr(session_id);
                /*2.第二步呢？获取一下session中的定时器*/
                WebSocketServer::timer_ptr timer = session->Timer();
                /*3.第三步? 判断定时器和超时时间的状态*/
                /*如果session内部没有设置定时器,并且超时时间设置为SESSION_FOREVER，则表示永久存在*/
                if (timer == nullptr && ms == SESSION_FOREVER)
                {
                        return;
                }
                /*如果session没有设置定时器，但是设置了超时时间,就给个定时器*/
                else if (timer == nullptr && ms == SESSION_TIMEOUT)
                {
                        WebSocketServer::timer_ptr tmp_timer = _server->set_timer(ms, std::bind(&SessionManager::Remove, this, session->SessionId()));
                        session->SetTimer(tmp_timer);
                }
                /*如果session存在了定时器，但是超时时间设置为SESSION_FOREVER*/
                else if (timer != nullptr && ms == SESSION_FOREVER)
                {
                        // 取消任务会导致执行回调函数
                        // 这里有个坑！cancel不是立即执行的（异步的），可能会存在延迟，有可能刚插入就执行释放了！
                        timer->cancel();
                        session->SetTimer(nullptr);
                        //添加定时任务，设置为0也不会立即执行！
                        _server->set_timer(0,std::bind(&SessionManager::AppendSession,this,session));
                }
                else if(timer != nullptr && ms != SESSION_FOREVER)
                {
                        //取消原有定时任务
                        timer->cancel();
                        _server->set_timer(0,std::bind(&SessionManager::AppendSession,this,session));
                        //重新加入
                        WebSocketServer::timer_ptr tmp_timer = _server->set_timer(ms,std::bind(&SessionManager::Remove, this, session->SessionId()));
                        session->SetTimer(tmp_timer);
                }
        }
        // 移除
        void Remove(LL session_id)
        {
                std::unique_lock<std::mutex> lock(_mtx);
                _sessions.erase(session_id);
        }
        ~SessionManager()
        {
                LOG(DEBUG, "session管理器被销毁\n");
        }
};